using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using TAAlert.Alerts;
using TAAlert.CommonUtils;

namespace TAAlert.Tests
{
    using NUnit.Framework;

    [TestFixture]
    class TestEMAEvaluator
    {
        private List<double> priceM =  new List<double>();
        public TestEMAEvaluator()
        {
            double[] tmp = { 1.000F, 6.306, 10.211, 6.509, 3.467, 3.586, 8.759, 27.187, 45.503, 30.329, 13.712, 10.141, 18.681, 56.021, 113.552, 92.137, 40.940, 23.611, 32.840, 90.811 };
            for (int i = 0; i < tmp.Length; ++i)
                priceM.Add(tmp[i]);
        }

        [Test]
        [Category("Calculation")]
        public void calcEMA()
        {
            int nEma = 2;
            double emaOld = 3.9516;
            double price = 8.7589;
            Assert.AreEqual(7.1564666666666668, EMAEvaluator.calcEMA(emaOld, nEma, price), "Exponential moving average wrong");
        }

        [Test]
        [Category("Calculation")]
        public void calcEMAArray()
        {
            int nEMA = 4;
            List<double> ema = EMAEvaluator.calcEMAArray(priceM, nEMA);

            Assert.AreEqual(22.4684098156544d, ema[10], "EMA[10]");

            Assert.AreEqual(priceM.Count, ema.Count, "Length of EMA aray");
            double totalEMA = 0;

            for (int i = 0; i < ema.Count; ++i)
                totalEMA += ema[i];
            Assert.AreEqual(545.30190361671566d, totalEMA, "Total EMA");
        }

        [Test]
        [Category("Calculation")]
        public void calcEMAVolatilityArray()
        {
            int nEMA = 10;
            int nOfPeriodsInYear = 252;
            List<double> vol = EMAEvaluator.calcEMAVolatilityArray(priceM, nEMA, nOfPeriodsInYear);
            Assert.AreEqual(36.869634164283319d, vol[10], "Volatility[10]");

            double totalVol = 0;
            foreach (double v in vol)
                totalVol += v;
            Assert.AreEqual(893.7062927244192d, totalVol, "Total EMA Volatility");}

        [Test]
        [Category("Calculation")]
        public void emaVolCutSignal()
        {
            // >>> emaVolCutSignal <<<
            // vol < volT, emaShort < emaLong
            Assert.AreEqual(Signal.Buy, EMAEvaluator.emaVolCutSignal(2, 1, 0.2, 0.3), "emaVolCutSignal: vol < volT, emaShort < emaLong");
            // vol < volT, emaShort > emaLong
            Assert.AreEqual(Signal.Sell, EMAEvaluator.emaVolCutSignal(1, 2, 0.2, 0.3), "emaVolCutSignal: vol < volT, emaShort > emaLong");
            // vol < volT, emaShort = emaLong
            Assert.AreEqual(Signal.Buy, EMAEvaluator.emaVolCutSignal(2, 2, 0.2, 0.3), "emaVolCutSignal: vol < volT, emaShort = emaLong");
            // vol > volT, emaShort < emaLong
            Assert.AreEqual(Signal.Neutral, EMAEvaluator.emaVolCutSignal(2, 1, 0.4, 0.3), "emaVolCutSignal: vol > volT, emaShort < emaLong");
            // vol > volT, emaShort > emaLong
            Assert.AreEqual(Signal.Neutral, EMAEvaluator.emaVolCutSignal(1, 2, 0.4, 0.3), "emaVolCutSignal: vol > volT, emaShort > emaLong");
            // vol > volT, emaShort = emaLong
            Assert.AreEqual(Signal.Neutral, EMAEvaluator.emaVolCutSignal(2, 2, 0.4, 0.3), "emaVolCutSignal: vol > volT, emaShort = emaLong");
            // vol = volT, emaShort < emaLong
            Assert.AreEqual(Signal.Neutral, EMAEvaluator.emaVolCutSignal(2, 1, 0.4, 0.4), "emaVolCutSignal: vol = volT, emaShort < emaLong");
            // vol = volT, emaShort > emaLong
            Assert.AreEqual(Signal.Neutral, EMAEvaluator.emaVolCutSignal(1, 2, 0.4, 0.4), "emaVolCutSignal: vol = volT, emaShort > emaLong");
            // vol = volT, emaShort = emaLong
            Assert.AreEqual(Signal.Neutral, EMAEvaluator.emaVolCutSignal(2, 2, 0.4, 0.4), "emaVolCutSignal: vol = volT, emaShort = emaLong");

            // >>> vemaSignal <<<
            int n1LowVol = 10, n2HighVol = 20;
            double quote=120, ema1LowVol=90, ema2HighVol=110, vol=0.2, volTreashold=0.3;
            // vol < volT, quote > ema1LowVol
            Assert.AreEqual(Signal.Buy, EMAEvaluator.vemaSignal(quote, vol, n1LowVol, ema1LowVol, n2HighVol, ema2HighVol, volTreashold), "vema: vol < volT, quote > ema1LowVol");
            // vol < volT, quote < ema1LowVol
            Assert.AreEqual(Signal.Sell, EMAEvaluator.vemaSignal(80, vol, n1LowVol, ema1LowVol, n2HighVol, ema2HighVol, volTreashold), "vema: vol < volT, quote < ema1LowVol");
            // vol > volT, quote > ema2HigVol
            Assert.AreEqual(Signal.Buy, EMAEvaluator.vemaSignal(quote, 0.4, n1LowVol, ema1LowVol, n2HighVol, ema2HighVol, volTreashold), "vema: vol > volT, quote > ema2HigVol");
            // vol > volT, quote < ema2HigVol
            Assert.AreEqual(Signal.Sell, EMAEvaluator.vemaSignal(100, 0.4, n1LowVol, ema1LowVol, n2HighVol, ema2HighVol, volTreashold), "vema: vol > volT, quote < ema2HigVol");
            // vol = volT, quote < ema2HigVol
            Assert.AreEqual(Signal.Sell, EMAEvaluator.vemaSignal(100, 0.3, n1LowVol, ema1LowVol, n2HighVol, ema2HighVol, volTreashold), "vema: vol = volT, quote < ema2HigVol");
            // vol < volT, n1=0
            Assert.AreEqual(Signal.Neutral, EMAEvaluator.vemaSignal(quote, vol, 0, ema1LowVol, n2HighVol, ema2HighVol, volTreashold), "vema: vol < volT, n1=0");
            // vol = volT, n2=0
            Assert.AreEqual(Signal.Neutral, EMAEvaluator.vemaSignal(100, 0.3, n1LowVol, ema1LowVol, 0, ema2HighVol, volTreashold), "vema: vol = volT, n2=0");
        }
    }
}
